#ifndef IMGEOMETRY_H
#define IMGEOMETRY_H

#include "imMaths.h"
#include "imGeometryBase.h"
#include "imGraphicsInterfaces.h"
#include <vector>
#include <fstream>

template <typename Real>
struct Plane;
template <typename Real>
struct AABB;
template <typename Real>
struct Polygon;

class iPrimitive {
protected:
	Vertex* Vertices;
	union {
		unsigned short* Indices;
		unsigned long* Indicesl;
	};
	unsigned int NumVertices, NumFaces, IndexSize; // Number of vertices, number of triangles, size of one index
public:
	Vertex* GetVertices(void) { return this->Vertices; };
	WORD* GetIndices(void) { return this->Indices; };

	uint GetNumVerts(void) { return this->NumVertices; };
	uint GetNumFaces(void) { return this->NumFaces; };

	virtual void Build(void) = 0;

	operator iPrimitive*(void) { return (iPrimitive*)this; };
};

class Mesh : public iMMObj {
protected:
	Vertex* Vertices;
	union {
		unsigned short* Indices;
		unsigned long* Indicesl;
	};
	uint NumVertices, NumIndices, NumFaces;
	unsigned char IndexSize, NumSubsets;
	int* SubsetStart;
	int* SubsetSize;
	imGraphics::iMeshDriver* Driver;
public:
	Mesh(void);
	Mesh(iPrimitive &Primitive);
	Mesh(char* Path);

	void BuildFromPrimitive(iPrimitive &Primitive);
	void LoadFromFile(std::ifstream*);
	void HookToDriver(void);
	void SaveToFile(std::ofstream*);

	void Predraw(void);
	void Draw(int Subset);
};

// Material
// Structure containing material information (colour, textures, etc.)
struct Material : iMMObj {
protected:
	Vector4 m_Diffuse,
			m_Specular;
	imGraphics::pTexture m_Tex[NUMTEXTURES];

	imGraphics::pShader m_Shader;

public:
	Material();
	
	void SetTexture(std::string &TexturePath, int Index);
	void SetTexture(imGraphics::iTexture* Tex, int Index);

	void SetShader(imGraphics::iShader *Shader);
	imGraphics::iShader* GetShader();

	void StartRender();
	void EndRender();
};

typedef MMPtr<Mesh> pMesh;
typedef MMPtr<Material> pMaterial;

#endif